#include "GLView.h"

GLView::GLView(){

    time    =   new QTime();
    time->start();

    valueTest=0.0f;
    lastTime=0;
    delta=0;

    starttime    =0 ;
    timeInterval =3000 ;
    frameCount=0  ;

    // Utilisé pour récupérer les événéments dans la fenêtre
    setFocusPolicy(Qt::StrongFocus);

    makeCurrent();
    glewInit();
    pressed=false;

    img = new Image();

    img->Load("../../Resources/original.tga");
    img->GenTexture();
    //img->Debug();

    scene   =   new SceneGraph();
    context =   new GLContext();

    context->LoadProgram("basic", "../../Resources/basique.frag", "../../Resources/basique_2D.vert");


    viewEntity      =   new View(PERSPECTIVE);
    trackview       =   new TrackView(vec4::Zero);

    UniformMat4 *   view    =   new UniformMat4(viewEntity->ViewMatrix());
    UniformMat4 *   proj    =   new UniformMat4(viewEntity->ProjectionMatrix());
    UniformMat4 *   model    =   new UniformMat4();

    view->m_Name    =   "ViewMatrix";
    proj->m_Name    =   "ProjectionMatrix";
    model->m_Name   =   "ModelMatrix";

    VertexTemplate  * vertexTemplate = new VertexTemplate();

    vertexTemplate->AddAttribute(4, "position");
    vertexTemplate->AddAttribute(4,"color");
    vertexTemplate->AddAttribute(4,"normal");
    vertexTemplate->AddAttribute(4,"texCoord1");


    Material * material     = new Material();
    material->SetVertexTemplate(*vertexTemplate);

    material->Program(*context->program);
    material->AddNewSharedUniform(view);
    material->AddNewSharedUniform(proj);

    material->AddNewUniform(model);

    material->GetLocations();

    mesh = &Mesh::Rect2D(1.0f, 1.0f, *vertexTemplate,0,1,2,3);
    Mesh * mesh2  = &Mesh::Rect3D(0.5f, 0.5f,0.5f, *vertexTemplate,0,1,2,3);


    Entity *    enti    =   new Entity();
    Entity *    enti2   =   new Entity();
    Entity *    enti3   =   new Entity();

    enti->m_Mesh    =   mesh;
    enti2->m_Mesh   =   mesh;
    enti3->m_Mesh   =   mesh2;

    material->AttachTo(enti);
    material->AttachTo(enti2);
    material->AttachTo(enti3);

    enti->m_Transform    =   new Transform( ((UniformMat4*)(enti->m_Uniforms.front()))->m_Matrix);
    enti2->m_Transform   =   new Transform( ((UniformMat4*)(enti2->m_Uniforms.front()))->m_Matrix);
    enti3->m_Transform   =   new Transform( ((UniformMat4*)(enti3->m_Uniforms.front()))->m_Matrix);

    scene->Append(*trackview);
    scene->Append(*enti);
    enti->Append(*enti2);
    scene->Append(*enti3);


    enti->m_Transform->Translation(2.0f,0.0f,-10.0f);
    enti2->m_Transform->RotationEuler(0.7,0.0,0.0);
    enti2->m_Transform->Translation(-2.0f,0.0f,-10.0f);

    enti3->m_Transform->Translation(10.0f,10.0f,-10.0f);

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(Refresh()));
    timer->start(0);

    enti->m_image=img;
    enti2->m_image=img;

    BufferObject::FeedBuffers();
}


void GLView::Refresh(){
    delta   =   time->elapsed()-lastTime;
    lastTime=time->elapsed();
    valueTest=time->elapsed();
    float pi = 3.14159265;
    //trackview->Update();

    //qDebug()<<"Trackview "<<trackview->m_Alpha;
    //viewEntity->GetTransform().LookAt(scene->m_Entities.at(1)->m_Childs.at(0)->m_Transform->WorldPosition());
    //viewEntity->GetTransform().LookAt(vec4(1.0f *0.0001*time->elapsed(), 4.0f*0.0001*time->elapsed(), -10.0f));

   /* qDebug()<< trackview->m_Transform->Position().x<<" "<<
               trackview->m_Transform->Position().y<<" "<<
               trackview->m_Transform->Position().z<<" "
<<
               trackview->m_Transform->Position().w;*/




    frameCount++;
    scene->m_Entities.at(1)->m_Transform->Translation(vec4::TurnAround(valueTest*0.0003f, pi* 6.0/10.0 , 3.0f, vec4(10.0,10.0f,-10.0f)));
    scene->m_Entities.at(1)->m_Transform->LookAt(vec4(10.0,10.0f,-10.0f));

    //*scene->m_Entities.at(2)->m_Transform->m_RotationMatrix=Quaternion(1.0f, 1.0f, 1.0f, time->elapsed()*0.0004f).RotationMatrix();
    *scene->m_Entities.at(2)->m_Transform->m_RotationMatrix=((Quaternion(0.0f, 0.0f, 1.0f,pi/4.0f))*(Quaternion(0.0f, 1.0f, 0.0f,valueTest*0.0003f))).RotationMatrix();
    scene->m_Entities.at(2)->m_Transform->Update();

    //scene->m_Entities.at(1)->m_Transform->RotateEuler(delta*0.005f,0.0f,0.0f);
   /* if(time->elapsed()> ( starttime + timeInterval)){
        starttime= time->elapsed();
     //   qDebug()<<"FPS : "<< (float)frameCount/3.0;
        frameCount=0;
    }*/


    updateGL();
}

void GLView::mouseMoveEvent(QMouseEvent *event){
    if(pressed==false){
        pressed=true;
        anchorX= event->x();
        anchorY=event->y();
    }else{
        float movx    =   anchorX- event->x();
        float movy    =   anchorY-event->y();
        float coef=0.01f;

       // qDebug()<<movx;

        movx    =   movx* coef;
        movy    =   movy*coef;

        anchorX= event->x();
        anchorY=event->y();

        trackview->m_Alpha+=movx;
        trackview->m_Teta+=movy;


        viewEntity->GetTransform().RotateEuler(-movy, -movx,0.0f);

        /*qDebug()<< viewEntity->GetTransform().Forward().x<<" "<<
                   viewEntity->GetTransform().Forward().y<<" "<<
                   viewEntity->GetTransform().Forward().z<<" "<<
                   viewEntity->GetTransform().Forward().w;
*/


/*
        qDebug()<< viewEntity->GetTransform().EulerAngles().x<<" "<<
                   viewEntity->GetTransform().EulerAngles().y<<" "<<
                   viewEntity->GetTransform().EulerAngles().z<<" "<<
                   viewEntity->GetTransform().EulerAngles().w;


    Matrix4 & mat = viewEntity->GetTransform().RotationMatrix();

    qDebug()<<"Rotation \n";
    qDebug()<< mat[0]<<" "<< mat[1]<<" "<< mat[2]<<" "<< mat[3];
    qDebug()<< mat[4]<<" "<< mat[5]<<" "<< mat[6]<<" "<< mat[7];
    qDebug()<< mat[8]<<" "<< mat[9]<<" "<< mat[10]<<" "<< mat[11];
    qDebug()<< mat[12]<<" "<< mat[13]<<" "<< mat[14]<<" "<< mat[15];
*/
    updateGL();
    }
}

void GLView::mouseReleaseEvent(QMouseEvent *event){
    pressed=false;
}

void GLView::keyPressEvent(QKeyEvent *key){

    vec4 val;

    if(key->key()== Qt::Key_Z){
        vec4 dir =viewEntity->GetTransform().Forward();
         if(dir.z>0){
             dir.y= -dir.y;
         }
        dir.z= -dir.z;
        val=dir*0.2f;
    }
     if(key->key()== Qt::Key_S){
        vec4 dir =viewEntity->GetTransform().Forward();
        if(dir.z>0){
            dir.y= -dir.y;
        }
         dir.z= -dir.z;
         val=dir*-0.2f;
    }

    if(key->key()== Qt::Key_Q){
        val =viewEntity->GetTransform().Right();
        if(val.z>0){
            val.y= -val.y;
        }
         val.z= -val.z;
          val=val*0.2f;
    }
     if(key->key()== Qt::Key_D){
        vec4 dir =  viewEntity->GetTransform().Right();
        if(dir.z>0){
            dir.y= -dir.y;
        }
        dir.z= -dir.z;
        val=dir*-0.2f;
    }

     if(key->key()== Qt::Key_Space){
         valueTest+=200.0f;
        Refresh();
     }

    viewEntity->GetTransform().Translate( val);


    updateGL();
}

void GLView::initializeGL(){

    glClearColor(0.7, 0.7, 0.7, 0.0);
    glEnable(GL_DEPTH_TEST);
}

void GLView::paintGL(){
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    BufferObject::Bind();
    //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    scene->Display();
}

void GLView::resizeGL(int w, int h){
    glViewport(0, 0, w, h);
}
